﻿using EnterpriseLibraryExtensions.PolicyInjection.UnityBridge.InterceptionStrategies;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity.ObjectBuilder;

namespace EnterpriseLibraryExtensions.PolicyInjection.UnityBridge
{
    /// <summary>
    /// This class is reponsible for adding an additional stage to the Unity pipeline.
    /// It will add <see href="PolicyInjectionStrategy"/> to the post initialization stage
    /// </summary>
    public class UnityPolicyExtension : UnityContainerExtension
    {
        private static readonly IInterceptorFactory InterceptionFactory = new InterceptorFactory();

        /// <summary>
        /// Creates a new Unity container that has been added this extension.
        /// </summary>
        /// <returns>A new instance of a class implementing the IUnityContainer interface.</returns>
        public static IUnityContainer CreateUnityContainer()
        {
            IUnityContainer container = new UnityContainer();
            container.AddNewExtension<Interception>();
            container.AddNewExtension<UnityPolicyExtension>();
            return container;
        }

        /// <summary>
        /// Inherited method. This method makes sure that the <see href="PolicyInjectionStrategy"/> is added
        /// to the Unity container being initialized.
        /// </summary>
        protected override void Initialize()
        {
            Context.Registering += ContextRegistering;
        }

        /// <summary>
        /// When types are registered on the Unity container, this method will apply a default interception
        /// policy for the type.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="Microsoft.Practices.Unity.RegisterEventArgs"/> instance containing the registration data.</param>
        private void ContextRegistering(object sender, RegisterEventArgs e)
        {
            if (e.TypeFrom != null)
            {
                IInstanceInterceptor instanceInterceptor = InterceptionFactory.GetInstanceInterceptor(e.TypeFrom);
                Context.Container.Configure<Interception>().SetDefaultInterceptorFor(e.TypeFrom, instanceInterceptor);
            }
        }
    }
}
